package com.example.lotterysystem.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.common.utils.JWTUtil;
import com.example.lotterysystem.common.utils.RegexUtil;
import com.example.lotterysystem.controller.param.ShortMessageLoginParam;
import com.example.lotterysystem.controller.param.UserLoginParam;
import com.example.lotterysystem.controller.param.UserPasswordLoginParam;
import com.example.lotterysystem.controller.param.UserRegisterParam;
import com.example.lotterysystem.dao.dataobject.Encrypt;
import com.example.lotterysystem.dao.dataobject.UserDO;
import com.example.lotterysystem.dao.mapper.UserMapper;
import com.example.lotterysystem.service.UserService;
import com.example.lotterysystem.service.VerificationCodeService;
import com.example.lotterysystem.service.dto.UserDTO;
import com.example.lotterysystem.service.dto.UserLoginDTO;
import com.example.lotterysystem.service.dto.UserRegisterDTO;
import com.example.lotterysystem.service.enums.UserIdentityEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @auther falls_vc
 * description:
 * @date 2025/5/10  16:31
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VerificationCodeService verificationCodeService;
    @Override
    public UserRegisterDTO register(UserRegisterParam userRegisterParam) {

        // 校验注册信息
        checkRegisterInfo(userRegisterParam);
        // 加密私密数据
        UserDO userDO=new UserDO();
        userDO.setUserName(userRegisterParam.getName());
        userDO.setEmail(userRegisterParam.getMail());
        userDO.setIdentity(userRegisterParam.getIdentity());
        userDO.setPhoneNumber(new Encrypt(userRegisterParam.getPhoneNumber()));
        if(StringUtils.hasText(userRegisterParam.getPassword())) {
            userDO.setPassword(DigestUtil.sha256Hex(userRegisterParam.getPassword()));
        }
        // 保存数据
        userMapper.insert(userDO);
        // 构造返回

        UserRegisterDTO userRegisterDTO=new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;
    }


    private void checkRegisterInfo(UserRegisterParam userRegisterParam) {
        if (null == userRegisterParam){
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }
        // 校验邮箱格式xxx@xxx.xxx
        if (!RegexUtil.checkMail(userRegisterParam.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        // 校验手机号格式
        if (!RegexUtil.checkMobile(userRegisterParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // 校验身份信息
        if (null == UserIdentityEnum.forName(userRegisterParam.getIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        // 管理员密码必填
        if (userRegisterParam.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.name())
                && !StringUtils.hasText(userRegisterParam.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }
        // 密码校验，至少6位
        if (StringUtils.hasText(userRegisterParam.getPassword()) &&
                !RegexUtil.checkPassword(userRegisterParam.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        // 邮箱是否被使用
        if (checkMailUsed(userRegisterParam.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }
        // 手机号是否被使用
        if (checkPhoneNumberUsed(userRegisterParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }

    }

    private boolean checkPhoneNumberUsed(String phoneNumber) {
        int count=userMapper.countByPhone(new Encrypt(phoneNumber));
        return count > 0;
    }

    private boolean checkMailUsed(String mail) {
        int count=userMapper.countByMail(mail);

        return count > 0;
    }

    @Override
    public UserLoginDTO login(UserLoginParam userLoginParam) {
        UserLoginDTO userLoginDTO;

        if (userLoginParam instanceof ShortMessageLoginParam param) {
            // 验证码登录
            userLoginDTO = loginByShortMessage(param);

        } else if (userLoginParam instanceof UserPasswordLoginParam param) {
            // 密码登录
            userLoginDTO = loginByPassword(param);
        } else {

            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }


        return userLoginDTO;
    }

    
    @Override
    public List<UserDTO> findUserInfo(UserIdentityEnum identity) {
        String identityString = null == identity? null : identity.name();
        // 查表
        List<UserDO> userDOList = userMapper.selectUserListByIdentity(identityString);
        List<UserDTO> userDTOList=userDOList.stream().map(
                userDO -> {
                    UserDTO userDTO=new UserDTO();
                    userDTO.setId(userDO.getId());
                    userDTO.setUserName(userDO.getUserName());
                    userDTO.setEmail(userDO.getEmail());
                    userDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());
                    userDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
                    return userDTO;
                }
        ).collect(Collectors.toList());
        return userDTOList;
    }


    private UserLoginDTO loginByPassword(UserPasswordLoginParam param) {
        UserDO userDO;

        if(RegexUtil.checkMobile(param.getLoginName())) { //电话号码登录

            userDO=userMapper.selectByPhoneNumber(new Encrypt(param.getLoginName()));
        } else if (RegexUtil.checkMail(param.getLoginName())) { // 邮箱号登录

            userDO=userMapper.selectByMail(param.getLoginName());
        } else {

            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_NOT_EXIST);
        }

        // 校验登录信息
        if(null == userDO) {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }else if (StringUtils.hasText(param.getMandatoryIdentity()) &&
                    !userDO.getIdentity().equalsIgnoreCase(param.getMandatoryIdentity())) {
//            身份信息不符
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }else if (!DigestUtil.sha256Hex(param.getPassword()).equals(userDO.getPassword())) {
            // 密码错误
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        // 生成token JWT令牌
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("identity",userDO.getIdentity());
        String token=JWTUtil.genJwt(claim);

        // 填写返回值
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
        return userLoginDTO;
    }

    // 使用的是邮箱 + 验证码 登录
    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam param) {

        if(!RegexUtil.checkMail(param.getLoginMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        // 获得数据
        UserDO userDO=userMapper.selectByMail(param.getLoginMail());
        if(userDO == null) {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }else if (StringUtils.hasText(param.getMandatoryIdentity()) &&
                    !param.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }

        // 验证码校验
        String code=verificationCodeService.getVerificationCode(param.getLoginMail());
        if(code == null) {
            throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_INNER_NOT_EXIST);

        } else if(!code.equals(param.getVerificationCode())) {
            throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);
        }

        // 返回
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("identity",userDO.getIdentity());

        String token=JWTUtil.genJwt(claim);
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));

        return userLoginDTO;
    }


}
